package main

import (
	"fmt"
	"knowledge-go/cpt/c_000_com"
	"unsafe"
)

var (
	d1User = c_000_com.User{
		Id:   123,
		Name: "张三",
	}
)

func main() {
	// 1.unsafe.Sizeof 函数返回操作数在内存中的字节大小，可以查看任意类型。
	// 	一个Sizeof函数调用是一个对应uintptr类型的常量表达式，因此返回的结果可以用作数组类型的长度大小，或者用作计算其他的常量。
	d1_sizeof()

	// 2.unsafe.Alignof 函数返回对应参数的类型需要对齐的倍数。 想要对其需要是8字节的整数位
	d1_alignof()

	// 3.unsafe.Offsetof函数的参数必须是一个字段 x.f, 然后返回 f 字段相对于 x 起始地址的偏移量, 包括可能的空洞.
	d1_offsetof()

	// 4.unsafe.Pointer获得任意类型参数的指针
	d1_pointer()
}

func d1_sizeof() {
	var s1 uintptr = unsafe.Sizeof(1)
	fmt.Println("unsafe.Sizeof 1:", s1)
	fmt.Println("unsafe.Sizeof 2:", unsafe.Sizeof(int32(1)))
	fmt.Println("unsafe.Sizeof 3:", unsafe.Sizeof(int64(1)))
	fmt.Println("unsafe.Sizeof 4:", unsafe.Sizeof(true))

	d2User := c_000_com.User{
		Id:   123,
		Name: "张三",
	}
	fmt.Println("unsafe.Sizeof user1:", unsafe.Sizeof(d1User))
	fmt.Println("unsafe.Sizeof user2:", unsafe.Sizeof(d2User))
}

func d1_alignof() {
	fmt.Println("unsafe.Alignof 1:", unsafe.Alignof(d1User))
}

func d1_offsetof() {
	fmt.Println("unsafe.Offsetof 1:", unsafe.Offsetof(d1User.Name))
	/*
		var x struct {
			a bool
			b int16
			c []int
		}

		32位系统：
		Sizeof(x)   = 16  Alignof(x)   = 4
		Sizeof(x.a) = 1   Alignof(x.a) = 1 Offsetof(x.a) = 0
		Sizeof(x.b) = 2   Alignof(x.b) = 2 Offsetof(x.b) = 2
		Sizeof(x.c) = 12  Alignof(x.c) = 4 Offsetof(x.c) = 4

		64位系统：
		Sizeof(x)   = 32  Alignof(x)   = 8
		Sizeof(x.a) = 1   Alignof(x.a) = 1 Offsetof(x.a) = 0
		Sizeof(x.b) = 2   Alignof(x.b) = 2 Offsetof(x.b) = 2
		Sizeof(x.c) = 24  Alignof(x.c) = 8 Offsetof(x.c) = 8
	*/
}

func d1_pointer() {
	var x struct {
		a bool
		b int16
		c []int
	}

	// 和 pb := &x.b 等价
	pb := (*int16)(unsafe.Pointer(uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.b)))
	*pb = 42
	fmt.Println(x.b) // "42"
}
